package com.mycompany.mvc.weixinUtils;

import com.mycompany.System.entity.retur.*;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.http.HttpServletRequest;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Jintao_Ma on 2017/9/10.
 * 微信相关解析
 */
public class ParseUtil {

    /**
     * 解析微信发来的请求（XML）
     *
     * @param request
     * @return
     * @throws Exception
     */
    public static Map<String, Object> parseXml(HttpServletRequest request) throws Exception {
        // 将解析结果存储在HashMap中
        Map<String, Object> map = new HashMap<String, Object>();

        // 从request中取得输入流
        InputStream inputStream = request.getInputStream();
        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(inputStream);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<Element> elementList = root.elements();

        // 遍历所有子节点
        for (Element e : elementList)
            map.put(e.getName(), e.getStringValue());

        // 释放资源
        inputStream.close();
        inputStream = null;

        return map;
    }

    /**
     * 文本消息对象转换成xml
     *
     * @param textMsgRe 文本消息对象
     * @return xml
     */
    public static String TextMsgReToXml(TextMsgRe textMsgRe) {
        xstream.alias("xml", textMsgRe.getClass());
        return xstream.toXML(textMsgRe);
    }

    /**
     * 图片消息对象转换成xml
     *
     * @param imageMsgRe 文本消息对象
     * @return xml
     */
    public static String ImageMsgReToXml(ImageMsgRe imageMsgRe) {
        xstream.alias("xml", imageMsgRe.getClass());
        return xstream.toXML(imageMsgRe);
    }

    /**
     * 语音消息对象转换成xml
     *
     * @param voiceMsgRe 文本消息对象
     * @return xml
     */
    public static String VoiceMsgReToXml(VoiceMsgRe voiceMsgRe) {
        xstream.alias("xml", voiceMsgRe.getClass());
        return xstream.toXML(voiceMsgRe);
    }

    /**
     * 视频消息对象转换成xml
     *
     * @param videoMsgRe 音乐消息对象
     * @return xml
     */
    public static String VideoMsgReToXml(VideoMsgRe videoMsgRe) {
        xstream.alias("xml", videoMsgRe.getClass());
        return xstream.toXML(videoMsgRe);
    }

    /**
     * 视频消息对象转换成xml
     *
     * @param musicMsgRe 音乐消息对象
     * @return xml
     */
    public static String MusicMsgReToXml(MusicMsgRe musicMsgRe) {
        xstream.alias("xml", musicMsgRe.getClass());
        return xstream.toXML(musicMsgRe);
    }

    /**
     * 图文消息对象转换成xml
     *
     * @param articleMsgRe 图文消息对象
     * @return xml
     */
    public static String ArticleMsgReToXml(ArticleMsgRe articleMsgRe) {
        xstream.alias("xml", articleMsgRe.getClass());
        xstream.alias("item", new ArticleRe().getClass());
        return xstream.toXML(articleMsgRe);
    }

    /**
     * 扩展xstream，使其支持CDATA块
     *
     * @date 2013-05-19
     */
    private static XStream xstream = new XStream(new XppDriver() {
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {
                // 对所有xml节点的转换都增加CDATA标记
                boolean cdata = true;

                public void startNode(String name, Class clazz) {
                    super.startNode(name, clazz);
                }

                protected void writeText(QuickWriter writer, String text) {
                    if (cdata) {
                        writer.write("<![CDATA[");
                        writer.write(text);
                        writer.write("]]>");
                    } else {
                        writer.write(text);
                    }
                }
            };
        }
    });


    /**
     * 从map集合中获取属性值
     *
     * @param <E>
     * @param map
     *            map集合
     * @param key
     *            键对
     * @param defaultValue
     *            默认值
     * @return
     * @author jiqinlin
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public final static <E> E get(Map map, Object key, E defaultValue) {
        Object o = map.get(key);
        if (o == null)
            return defaultValue;
        return (E) o;
    }

    /**
     * Map集合对象转化成 JavaBean集合对象
     *
     * @param javaBean JavaBean实例对象
     * @param mapList Map数据集对象
     * @return
     * @author jqlin
     */
    @SuppressWarnings({ "rawtypes" })
    public static <T> List<T> map2Java(T javaBean, List<Map> mapList) {
        if(mapList == null || mapList.isEmpty()){
            return null;
        }
        List<T> objectList = new ArrayList<T>();

        T object = null;
        for(Map map : mapList){
            if(map != null){
                object = map2Java(javaBean, map);
                objectList.add(object);
            }
        }

        return objectList;

    }

    /**
     * Map对象转化成 JavaBean对象
     *
     * @param javaBean JavaBean实例对象
     * @param map Map对象
     * @return
     * @author jqlin
     */
    @SuppressWarnings({ "rawtypes","unchecked", "hiding" })
    public static <T> T map2Java(T javaBean, Map map) {
        try {
            // 获取javaBean属性
            BeanInfo beanInfo = Introspector.getBeanInfo(javaBean.getClass());
            // 创建 JavaBean 对象
            Object obj = javaBean.getClass().newInstance();

            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            if (propertyDescriptors != null && propertyDescriptors.length > 0) {
                String propertyName = null; // javaBean属性名
                Object propertyValue = null; // javaBean属性值
                for (PropertyDescriptor pd : propertyDescriptors) {
                    propertyName = pd.getName();
                    if(StringUtils.isNotEmpty(propertyName)){
                        //getPropertyDescriptors的第一个字母大写
                        propertyName = propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);
                        if (map.containsKey(propertyName)) {
                            propertyValue = map.get(propertyName);
                            pd.getWriteMethod().invoke(obj, new Object[] { propertyValue });
                        }
                    }
                }
                return (T) obj;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * JavaBean对象转化成Map对象
     *
     * @param javaBean
     * @return
     * @author jqlin
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static Map java2Map(Object javaBean) {
        Map map = new HashMap();

        try {
            // 获取javaBean属性
            BeanInfo beanInfo = Introspector.getBeanInfo(javaBean.getClass());

            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            if (propertyDescriptors != null && propertyDescriptors.length > 0) {
                String propertyName = null; // javaBean属性名
                Object propertyValue = null; // javaBean属性值
                for (PropertyDescriptor pd : propertyDescriptors) {
                    propertyName = pd.getName();
                    if (!propertyName.equals("class")) {
                        Method readMethod = pd.getReadMethod();
                        propertyValue = readMethod.invoke(javaBean, new Object[0]);
                        map.put(propertyName, propertyValue);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return map;
    }

}
